package icu.guodapeng.oauth2.config

import icu.guodapeng.oauth2.component.JwtTokenEnhancer
import icu.guodapeng.oauth2.service.impl.UserServiceImpl
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.io.ClassPathResource
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer
import org.springframework.security.oauth2.provider.token.TokenEnhancer
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory
import java.security.KeyPair
import javax.annotation.Resource

/**
 * 认证服务器配置
 */
@Configuration
@EnableAuthorizationServer
class Oauth2ServerConfig : AuthorizationServerConfigurerAdapter() {

    @Resource
    lateinit var passwordEncoder: PasswordEncoder

    @Resource
    lateinit var authenticationManager: AuthenticationManager

    @Resource
    lateinit var userService: UserServiceImpl

    override fun configure(clients: ClientDetailsServiceConfigurer) {
        clients.inMemory()
            .withClient("client-app") // 配置 client_id
            .secret(passwordEncoder.encode("123456")) // 配置 client_secret
            .scopes("all") // 配置申请的权限范围
            .authorizedGrantTypes("password", "refresh_token") // grant_type 表示授权类型, 密码模式 password
            .accessTokenValiditySeconds(3600) // 访问 token 的有效期
            .refreshTokenValiditySeconds(86400) // 刷新 token 的有效期
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
        val delegates = ArrayList<TokenEnhancer>()
        delegates.add(JwtTokenEnhancer())
        delegates.add(accessTokenConverter())

        val enhancerChain = TokenEnhancerChain()
        enhancerChain.setTokenEnhancers(delegates) // 配置 JWT 的内容增强器

        endpoints
            .userDetailsService(userService) // 配置加载用户信息的服务
            .authenticationManager(authenticationManager) // 密码授予的 AuthenticationManager
            .accessTokenConverter(accessTokenConverter())
            .tokenEnhancer(enhancerChain)
    }

    @Bean
    fun accessTokenConverter(): JwtAccessTokenConverter {
        val jwtAccessTokenConverter = JwtAccessTokenConverter()
        jwtAccessTokenConverter.setKeyPair(keyPair())
        return jwtAccessTokenConverter
    }

    @Bean
    fun keyPair(): KeyPair = KeyStoreKeyFactory(
        ClassPathResource("jwt.jks"), "123456".toCharArray()
    ).getKeyPair("jwt", "123456".toCharArray())
}
